#pragma once

#include "Thread.hpp"
#include "LockGuard.hpp"
#include <vector>
#include <queue>
#include <iostream>
#include <unistd.h>
#include <pthread.h>

// 这里是写的线程池
using namespace ThreadNs;

template <class T>
class ThreadPool;
const int gnum = 5;

template <class T>
class ThreadData
{
public:
    ThreadPool<T> *threadpool;
    std::string name;

public:
    ThreadData(ThreadPool<T> *tp, const std::string &n) : threadpool(tp), name(n)
    {
    }
};

template <class T>
// 线程池
class ThreadPool
{
private:
    // 启动线程池之后，里面线程要做的任务
    static void *handlerTask(void *args)
    {
        ThreadData<T> *td = (ThreadData<T> *)args;
        ThreadPool<T> *threadpool = static_cast<ThreadPool<T> *>(args);
        while (true)
        {
            td->threadpool->lockQueue();

            LockGuard(td->threadpool->mutex());
            while (td->threadpool->isQueueEmpty())
            {
                td->threadpool->threadWait();
            }
            T t = td->threadpool->pop(); // pop的本质,将任务从公共队列中，拿到线程自己独立的栈中
            td->threadpool->unlockQueue();
            std::cout << td->name << "获取了一个任务：" << t.toTaskString() << "并处理完成，结果是：" << t() << std::endl;
        }
        delete td;
        return nullptr;
    }

public:
    void lockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void unlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    bool isQueueEmpty()
    {
        return _task_queue.empty();
    }
    void threadWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }
    pthread_mutex_t *mutex()
    {
        return &_mutex;
    }

public:
    ThreadPool(const int &num = gnum) : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        // 创建一批线程
        for (int i = 0; i < num; i++)
        {
            _threads.push_back(new Thread());
        }
    }
    // 启动线程
    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handlerTask, td);
            std::cout << t->threadname() << "start..." << std::endl;
        }
    }
    void push(const T &in)
    {
        pthread_mutex_lock(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
        pthread_mutex_unlock(&_mutex);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &t : _threads)
            delete t;
    }

private:
    int _num;                       // 表示这个线程池中有几个线程
    std::vector<Thread *> _threads; // 一批线程对象  用vector管理这批线程
    std::queue<T> _task_queue;      // 任务队列(共享资源)
    pthread_mutex_t _mutex;         // 锁
    pthread_cond_t _cond;           // 条件变量
};
